//! Views of a remote mailbox.

use aspect_msgqueue::{Msg, MsgRange, MsgSummary};

/// Description of the range of messages we can read from an outbox.
#[derive(Clone, Debug)]
pub struct QueueOutboxView {
    /// The earliest message available to be fetched.
    first_avail_idx: u64,

    /// Last message index available to be fetched.
    last_msg_idx: u64,

    /// Recent messages that have been sent, as a way to know which messages
    /// we've already received or not.
    ///
    /// I'm not completely sure how this is going to work.
    recent_msgs: Vec<MsgSummary>,
}

impl QueueOutboxView {
    pub fn new(first_avail_idx: u64, last_msg_idx: u64, recent_msgs: Vec<MsgSummary>) -> Self {
        Self {
            first_avail_idx,
            last_msg_idx,
            recent_msgs,
        }
    }

    pub fn first_avail_idx(&self) -> u64 {
        self.first_avail_idx
    }

    pub fn last_msg_idx(&self) -> u64 {
        self.last_msg_idx
    }

    pub fn recent_msgs(&self) -> &[MsgSummary] {
        &self.recent_msgs
    }

    /// Constructs a [`MsgRange`] to request some messages starting from the
    /// earliest available message.b
    pub fn get_request_range(&self, limit: u32) -> MsgRange {
        let total_avail = self.last_msg_idx - self.first_avail_idx;
        let want = u64::min(total_avail, limit as u64) as u32;
        MsgRange::new(self.first_avail_idx, want)
    }
}

/// Describes recent state of a remote inbox we can write to.
#[derive(Clone, Debug)]
pub struct QueueInboxView {
    /// The index of the last message received by the inbox.
    last_msg_idx: u64,

    /// List of recent message summaries, in any order.
    ///
    /// This is used to help dedup senders remember that some messages have been.
    recent_msgs: Vec<MsgSummary>,
}

impl QueueInboxView {
    pub fn new(last_msg_idx: u64, recent_msgs: Vec<MsgSummary>) -> Self {
        Self {
            last_msg_idx,
            recent_msgs,
        }
    }

    pub fn last_msg_idx(&self) -> u64 {
        self.last_msg_idx
    }

    pub fn recent_msgs(&self) -> &[MsgSummary] {
        &self.recent_msgs
    }
}

/// A message and its index so it can exist on its own.
#[derive(Clone, Debug)]
pub struct ReceivedMsg {
    idx: u64,
    msg: Msg,
}

impl ReceivedMsg {
    pub fn new(idx: u64, msg: Msg) -> Self {
        Self { idx, msg }
    }

    pub fn idx(&self) -> u64 {
        self.idx
    }

    pub fn msg(&self) -> &Msg {
        &self.msg
    }
}
